const canvas = document.querySelector("#canvas");
const context = canvas.getContext("2d");

const AXIS_MARGIN = 40;
const AXIS_ORIGIN = { x: AXIS_MARGIN, y: canvas.height - AXIS_MARGIN };
const AXIS_RIGHT = canvas.width - 40;
const AXIS_TOP = AXIS_MARGIN;
const LINE_WIDTH = 0.5;

let drawingSurfaceImageData;
let rubberbandRect = {};
let mousedown = {};
let dragging;
let guidewries = true;

function drawVerticalAxisTicks(step) {
    const { x, y } = AXIS_ORIGIN;
    context.lineWidth = 0.5;
    context.beginPath();
    context.moveTo(x + LINE_WIDTH, y);
    context.lineTo(x + LINE_WIDTH, AXIS_TOP);
    context.stroke();
    for (
        let i = step + 0.5;
        i < context.canvas.height - AXIS_MARGIN * 2;
        i += step
    ) {
        let endX = 0.2;
        if (parseInt(i / 10) % 5 === 0) {
            endX = 0.4;
            context.lineWidth = 1.3;
        } else {
            context.lineWidth = 0.5;
        }
        context.beginPath();
        context.moveTo(x, i + AXIS_MARGIN);
        context.lineTo(x + AXIS_MARGIN * endX, i + AXIS_MARGIN);
        context.stroke();
    }
}

function drawHorizontalAxis(step) {
    const { x, y } = AXIS_ORIGIN;
    context.lineWidth = 0.5;
    context.beginPath();
    context.moveTo(x + LINE_WIDTH, y + LINE_WIDTH);
    context.lineTo(AXIS_RIGHT + LINE_WIDTH, y + LINE_WIDTH);
    context.stroke();
    for (
        let i = step + 0.5;
        i < context.canvas.width - AXIS_MARGIN * 2;
        i += step
    ) {
        let beginY = 0.2;
        if (parseInt(i / 10) % 5 === 0) {
            beginY = 0.4;
            context.lineWidth = 1.3;
        } else {
            context.lineWidth = 0.5;
        }
        context.beginPath();
        context.moveTo(
            i + AXIS_MARGIN,
            context.canvas.height - AXIS_MARGIN - AXIS_MARGIN * beginY
        );
        context.lineTo(i + AXIS_MARGIN, context.canvas.height - AXIS_MARGIN);
        context.stroke();
    }
}

function windowToCanvas(x, y) {
    const bbox = canvas.getBoundingClientRect();
    return {
        x: x - bbox.left * (canvas.width / bbox.width),
        y: y - bbox.top * (canvas.height / bbox.height)
    };
}

//保存图像
function saveDrawingSurface() {
    drawingSurfaceImageData = context.getImageData(
        0,
        0,
        canvas.width,
        canvas.height
    );
}

//恢复图像
function restoreDrawingSurface() {
    context.putImageData(drawingSurfaceImageData, 0, 0);
}
// 更新矩形
function updateRubberbandRectangle(loc) {
    rubberbandRect.width = Math.abs(loc.x - mousedown.x);
    rubberbandRect.height = Math.abs(loc.y - mousedown.y);

    if (loc.x > mousedown.x) rubberbandRect.left = mousedown.x;
    else rubberbandRect.left = loc.x;

    if (loc.y > mousedown.y) rubberbandRect.top = mousedown.y;
    else rubberbandRect.top = loc.y;
}

// 画线
function drawRubberbandShape(loc) {
    context.beginPath();
    context.moveTo(mousedown.x, mousedown.y);
    context.lineTo(loc.x, loc.y);
    context.stroke();
}

//画线
function updateRubberband(loc) {
    updateRubberbandRectangle(loc);
    drawRubberbandShape(loc);
}

// 横向辅助线
function drawVerticalLine(x) {
    context.beginPath();
    context.moveTo(x + 0.5, 0);
    context.lineTo(x + 0.5, context.canvas.height);
    context.stroke();
}

//纵向辅助线
function drawHorizontalLine(y) {
    context.beginPath();
    context.moveTo(0, y + 0.5);
    context.lineTo(context.canvas.width, y + 0.5);
    context.stroke();
}

//画辅助线
function drawGuidewires(x, y) {
    context.save();
    context.strokeStyle = "rgba(0, 0, 230, 0.4)";
    context.lineWidth = 0.5;
    drawVerticalLine(x);
    drawHorizontalLine(y);
    context.restore();
}

function draw() {
    drawVerticalAxisTicks(10);
    drawHorizontalAxis(10);
}

draw();

canvas.onmousedown = e => {
    let loc = windowToCanvas(e.clientX, e.clientY);
    e.preventDefault();
    saveDrawingSurface(); // 鼠标按下保存当前干净帧 （原始图像）
    mousedown.x = loc.x;  // 获取鼠标 x坐标
    mousedown.y = loc.y;  // 获取鼠标 y坐标
    dragging = true;      // 开启拖动开关
};

canvas.onmousemove = e => {
    let loc;
    if (dragging) { // 如果可拖动
        e.preventDefault();
        loc = windowToCanvas(e.clientX, e.clientY);
        restoreDrawingSurface(); // 将干净帧返还当前画布 （清除上一帧的 线段 + 辅助线）
        updateRubberband(loc);   // 更新图形 位置
        if (guidewries) { // 是否画辅助线
            drawGuidewires(loc.x, loc.y);
        }
    }
};

canvas.onmouseup = e => {
    let loc = windowToCanvas(e.clientX, e.clientY);
    restoreDrawingSurface(); // 将干净镇返还当前画布 （清除辅助线）
    updateRubberband(loc);
    dragging = false;
};
